package com.stone.serverless.sdk.handler;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.stone.serverless.sdk.loader.ModuleClassLoader;
import com.stone.serverless.sdk.constant.ClassPathConstant;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @Description: TODO
 * @Author: MECHREVO
 * @Date: 2022/1/25 13:35
 * @Version: 1.0.0
 */
public class RemoteInvokeHandler implements InvocationHandler, MethodInterceptor {

    private String componentName;

    private String version;


    public RemoteInvokeHandler(String componentName, String version) {
        this.componentName = componentName;
        this.version = version;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return this.proxy(proxy, method, args);
    }

    public Object proxy(Object proxy, Method method, Object[] args) throws Throwable {
        if (ArrayUtil.contains(ComponentInvocationHandler.EXCLUDE_METHOD_NAME, method.getName())) {
            return method.invoke(proxy, args);
        }
        Object rpcService = null;
        //获取rpcService
        ClassLoader classLoader = this.getClass().getClassLoader();
        Class<?> superclass = classLoader.getClass().getSuperclass();
        if (null == superclass) {
            return null;
        }
        Class<?>[] interfaces = superclass.getInterfaces();
        if (null == interfaces || interfaces.length == 0) {
            return null;
        }
        if (interfaces[0].getName().equals(ModuleClassLoader.class.getName())) {
            Object componentConsumer = ReflectUtil.invoke(classLoader, "getComponentConsumer");
            if (ObjectUtil.isNull(componentConsumer)) {
                return null;
            }
            Map<String, Object> consumerBeanMapping = ReflectUtil.invoke(componentConsumer, "getConsumerBeanMapping");
            rpcService = consumerBeanMapping.get(ClassPathConstant.REMOTE_CALL_SERVICE_CLASS_PATH);
        }
        if (null==rpcService) {
            System.out.println("找不到 rpc client "+ClassPathConstant.REMOTE_CALL_SERVICE_CLASS_PATH);
            return null;
        }
        Object invoke = ReflectUtil.invoke(rpcService, "invoke", componentName, version, args, method);
        return invoke;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        return this.proxy(o, method, objects);
    }
}
